diff a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp --- a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. @@ -427,42 +427,10 @@ __ jmp(handler_addr); return start; } - - //---------------------------------------------------------------------------------------------------- - // Implementation of int32_t atomic_xchg(int32_t exchange_value, volatile int32_t* dest) - // used by Atomic::xchg(volatile int32_t* dest, int32_t exchange_value) - // - // xchg exists as far back as 8086, lock needed for MP only - // Stack layout immediately after call: - // - // 0 [ret addr ] <--- rsp - // 1 [ ex ] - // 2 [ dest ] - // - // Result: *dest <- ex, return (old *dest) - // - // Note: win32 does not currently use this code - - address generate_atomic_xchg() { - StubCodeMark mark(this, "StubRoutines", "atomic_xchg"); - address start = __ pc(); - - __ push(rdx); - Address exchange(rsp, 2 * wordSize); - Address dest_addr(rsp, 3 * wordSize); - __ movl(rax, exchange); - __ movptr(rdx, dest_addr); - __ xchgl(rax, Address(rdx, 0)); - __ pop(rdx); - __ ret(0); - - return start; - } - //---------------------------------------------------------------------------------------------------- // Support for void verify_mxcsr() // // This routine is used with -Xcheck:jni to verify that native // JNI code does not return to Java code without restoring the @@ -3795,13 +3763,10 @@ StubRoutines::_call_stub_entry = generate_call_stub(StubRoutines::_call_stub_return_address); // is referenced by megamorphic call StubRoutines::_catch_exception_entry = generate_catch_exception(); - // These are currently used by Solaris/Intel - StubRoutines::_atomic_xchg_entry = generate_atomic_xchg(); - // platform dependent create_control_words(); StubRoutines::x86::_verify_mxcsr_entry = generate_verify_mxcsr(); StubRoutines::x86::_verify_fpu_cntrl_wrd_entry = generate_verify_fpu_cntrl_wrd(); diff a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. @@ -550,174 +550,10 @@ __ jmp(rbx); return start; } - // Implementation of jint atomic_xchg(jint add_value, volatile jint* dest) - // used by Atomic::xchg(volatile jint* dest, jint exchange_value) - // - // Arguments : - // c_rarg0: exchange_value - // c_rarg0: dest - // - // Result: - // *dest <- ex, return (orig *dest) - address generate_atomic_xchg() { - StubCodeMark mark(this, "StubRoutines", "atomic_xchg"); - address start = __ pc(); - - __ movl(rax, c_rarg0); // Copy to eax we need a return value anyhow - __ xchgl(rax, Address(c_rarg1, 0)); // automatic LOCK - __ ret(0); - - return start; - } - - // Implementation of intptr_t atomic_xchg(jlong add_value, volatile jlong* dest) - // used by Atomic::xchg(volatile jlong* dest, jlong exchange_value) - // - // Arguments : - // c_rarg0: exchange_value - // c_rarg1: dest - // - // Result: - // *dest <- ex, return (orig *dest) - address generate_atomic_xchg_long() { - StubCodeMark mark(this, "StubRoutines", "atomic_xchg_long"); - address start = __ pc(); - - __ movptr(rax, c_rarg0); // Copy to eax we need a return value anyhow - __ xchgptr(rax, Address(c_rarg1, 0)); // automatic LOCK - __ ret(0); - - return start; - } - - // Support for jint atomic::atomic_cmpxchg(jint exchange_value, volatile jint* dest, - // jint compare_value) - // - // Arguments : - // c_rarg0: exchange_value - // c_rarg1: dest - // c_rarg2: compare_value - // - // Result: - // if ( compare_value == *dest ) { - // *dest = exchange_value - // return compare_value; - // else - // return *dest; - address generate_atomic_cmpxchg() { - StubCodeMark mark(this, "StubRoutines", "atomic_cmpxchg"); - address start = __ pc(); - - __ movl(rax, c_rarg2); - __ lock(); - __ cmpxchgl(c_rarg0, Address(c_rarg1, 0)); - __ ret(0); - - return start; - } - - // Support for int8_t atomic::atomic_cmpxchg(int8_t exchange_value, volatile int8_t* dest, - // int8_t compare_value) - // - // Arguments : - // c_rarg0: exchange_value - // c_rarg1: dest - // c_rarg2: compare_value - // - // Result: - // if ( compare_value == *dest ) { - // *dest = exchange_value - // return compare_value; - // else - // return *dest; - address generate_atomic_cmpxchg_byte() { - StubCodeMark mark(this, "StubRoutines", "atomic_cmpxchg_byte"); - address start = __ pc(); - - __ movsbq(rax, c_rarg2); - __ lock(); - __ cmpxchgb(c_rarg0, Address(c_rarg1, 0)); - __ ret(0); - - return start; - } - - // Support for int64_t atomic::atomic_cmpxchg(int64_t exchange_value, - // volatile int64_t* dest, - // int64_t compare_value) - // Arguments : - // c_rarg0: exchange_value - // c_rarg1: dest - // c_rarg2: compare_value - // - // Result: - // if ( compare_value == *dest ) { - // *dest = exchange_value - // return compare_value; - // else - // return *dest; - address generate_atomic_cmpxchg_long() { - StubCodeMark mark(this, "StubRoutines", "atomic_cmpxchg_long"); - address start = __ pc(); - - __ movq(rax, c_rarg2); - __ lock(); - __ cmpxchgq(c_rarg0, Address(c_rarg1, 0)); - __ ret(0); - - return start; - } - - // Implementation of jint atomic_add(jint add_value, volatile jint* dest) - // used by Atomic::add(volatile jint* dest, jint add_value) - // - // Arguments : - // c_rarg0: add_value - // c_rarg1: dest - // - // Result: - // *dest += add_value - // return *dest; - address generate_atomic_add() { - StubCodeMark mark(this, "StubRoutines", "atomic_add"); - address start = __ pc(); - - __ movl(rax, c_rarg0); - __ lock(); - __ xaddl(Address(c_rarg1, 0), c_rarg0); - __ addl(rax, c_rarg0); - __ ret(0); - - return start; - } - - // Implementation of intptr_t atomic_add(intptr_t add_value, volatile intptr_t* dest) - // used by Atomic::add(volatile intptr_t* dest, intptr_t add_value) - // - // Arguments : - // c_rarg0: add_value - // c_rarg1: dest - // - // Result: - // *dest += add_value - // return *dest; - address generate_atomic_add_long() { - StubCodeMark mark(this, "StubRoutines", "atomic_add_long"); - address start = __ pc(); - - __ movptr(rax, c_rarg0); // Copy to eax we need a return value anyhow - __ lock(); - __ xaddptr(Address(c_rarg1, 0), c_rarg0); - __ addptr(rax, c_rarg0); - __ ret(0); - - return start; - } - // Support for intptr_t OrderAccess::fence() // // Arguments : // // Result: @@ -6330,17 +6166,10 @@ // is referenced by megamorphic call StubRoutines::_catch_exception_entry = generate_catch_exception(); // atomic calls - StubRoutines::_atomic_xchg_entry = generate_atomic_xchg(); - StubRoutines::_atomic_xchg_long_entry = generate_atomic_xchg_long(); - StubRoutines::_atomic_cmpxchg_entry = generate_atomic_cmpxchg(); - StubRoutines::_atomic_cmpxchg_byte_entry = generate_atomic_cmpxchg_byte(); - StubRoutines::_atomic_cmpxchg_long_entry = generate_atomic_cmpxchg_long(); - StubRoutines::_atomic_add_entry = generate_atomic_add(); - StubRoutines::_atomic_add_long_entry = generate_atomic_add_long(); StubRoutines::_fence_entry = generate_orderaccess_fence(); // platform dependent StubRoutines::x86::_get_previous_fp_entry = generate_get_previous_fp(); StubRoutines::x86::_get_previous_sp_entry = generate_get_previous_sp(); diff a/src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp b/src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp --- a/src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp +++ b/src/hotspot/os_cpu/windows_x86/atomic_windows_x86.hpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. @@ -23,10 +23,11 @@ */ #ifndef OS_CPU_WINDOWS_X86_ATOMIC_WINDOWS_X86_HPP #define OS_CPU_WINDOWS_X86_ATOMIC_WINDOWS_X86_HPP +#include #include "runtime/os.hpp" // Note that in MSVC, volatile memory accesses are explicitly // guaranteed to have acquire release semantics (w.r.t. compiler // reordering) and therefore does not even need a compiler barrier @@ -36,25 +37,10 @@ template<> inline void ScopedFence::postfix() { } template<> inline void ScopedFence::prefix() { } template<> inline void ScopedFence::prefix() { } template<> inline void ScopedFence::postfix() { OrderAccess::fence(); } -// The following alternative implementations are needed because -// Windows 95 doesn't support (some of) the corresponding Windows NT -// calls. Furthermore, these versions allow inlining in the caller. -// (More precisely: The documentation for InterlockedExchange says -// it is supported for Windows 95. However, when single-stepping -// through the assembly code we cannot step into the routine and -// when looking at the routine address we see only garbage code. -// Better safe then sorry!). Was bug 7/31/98 (gri). -// -// Performance note: On uniprocessors, the 'lock' prefixes are not -// necessary (and expensive). We should generate separate cases if -// this becomes a performance problem. - -#pragma warning(disable: 4035) // Disables warnings reporting missing return statement - template struct Atomic::PlatformAdd { template D add_and_fetch(D volatile* dest, I add_value, atomic_memory_order order) const; @@ -62,37 +48,44 @@ D fetch_and_add(D volatile* dest, I add_value, atomic_memory_order order) const { return add_and_fetch(dest, add_value, order) - add_value; } }; -#ifdef AMD64 -template<> -template -inline D Atomic::PlatformAdd<4>::add_and_fetch(D volatile* dest, I add_value, - atomic_memory_order order) const { - return add_using_helper(os::atomic_add_func, dest, add_value); -} +// The Interlocked* APIs only take long and will not accept __int32. That is +// acceptable on Windows, since long is a 32-bits integer type, + +#define DEFINE_STUB_ADD(ByteSize, StubType, StubName) \ + template<> \ + template \ + inline D Atomic::PlatformAdd::add_and_fetch(D volatile* dest, \ + I add_value, \ + atomic_memory_order order) const { \ + STATIC_ASSERT(ByteSize == sizeof(D)); \ + return PrimitiveConversions::cast( \ + StubName(reinterpret_cast(dest), \ + PrimitiveConversions::cast(add_value))); \ + } -template<> -template -inline D Atomic::PlatformAdd<8>::add_and_fetch(D volatile* dest, I add_value, - atomic_memory_order order) const { - return add_using_helper(os::atomic_add_long_func, dest, add_value); -} +DEFINE_STUB_ADD(4, long, InterlockedAdd) +DEFINE_STUB_ADD(8, __int64, InterlockedAdd64) + +#undef DEFINE_STUB_ADD #define DEFINE_STUB_XCHG(ByteSize, StubType, StubName) \ template<> \ template \ inline T Atomic::PlatformXchg::operator()(T volatile* dest, \ T exchange_value, \ atomic_memory_order order) const { \ STATIC_ASSERT(ByteSize == sizeof(T)); \ - return xchg_using_helper(StubName, dest, exchange_value); \ + return PrimitiveConversions::cast( \ + StubName(reinterpret_cast(dest), \ + PrimitiveConversions::cast(exchange_value))); \ } -DEFINE_STUB_XCHG(4, int32_t, os::atomic_xchg_func) -DEFINE_STUB_XCHG(8, int64_t, os::atomic_xchg_long_func) +DEFINE_STUB_XCHG(4, long, InterlockedExchange) +DEFINE_STUB_XCHG(8, __int64, InterlockedExchange64) #undef DEFINE_STUB_XCHG #define DEFINE_STUB_CMPXCHG(ByteSize, StubType, StubName) \ template<> \ @@ -100,106 +93,25 @@ inline T Atomic::PlatformCmpxchg::operator()(T volatile* dest, \ T compare_value, \ T exchange_value, \ atomic_memory_order order) const { \ STATIC_ASSERT(ByteSize == sizeof(T)); \ - return cmpxchg_using_helper(StubName, dest, compare_value, exchange_value); \ + return PrimitiveConversions::cast( \ + StubName(reinterpret_cast(dest), \ + PrimitiveConversions::cast(exchange_value), \ + PrimitiveConversions::cast(compare_value))); \ } -DEFINE_STUB_CMPXCHG(1, int8_t, os::atomic_cmpxchg_byte_func) -DEFINE_STUB_CMPXCHG(4, int32_t, os::atomic_cmpxchg_func) -DEFINE_STUB_CMPXCHG(8, int64_t, os::atomic_cmpxchg_long_func) +DEFINE_STUB_CMPXCHG(1, char, _InterlockedCompareExchange8) // Use the intrinsic as InterlockedCompareExchange8 does not exist +DEFINE_STUB_CMPXCHG(4, long, InterlockedCompareExchange) +DEFINE_STUB_CMPXCHG(8, __int64, InterlockedCompareExchange64) #undef DEFINE_STUB_CMPXCHG -#else // !AMD64 - -template<> -template -inline D Atomic::PlatformAdd<4>::add_and_fetch(D volatile* dest, I add_value, - atomic_memory_order order) const { - STATIC_ASSERT(4 == sizeof(I)); - STATIC_ASSERT(4 == sizeof(D)); - __asm { - mov edx, dest; - mov eax, add_value; - mov ecx, eax; - lock xadd dword ptr [edx], eax; - add eax, ecx; - } -} - -template<> -template -inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest, - T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(4 == sizeof(T)); - // alternative for InterlockedExchange - __asm { - mov eax, exchange_value; - mov ecx, dest; - xchg eax, dword ptr [ecx]; - } -} - -template<> -template -inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest, - T compare_value, - T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(1 == sizeof(T)); - // alternative for InterlockedCompareExchange - __asm { - mov edx, dest - mov cl, exchange_value - mov al, compare_value - lock cmpxchg byte ptr [edx], cl - } -} - -template<> -template -inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest, - T compare_value, - T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(4 == sizeof(T)); - // alternative for InterlockedCompareExchange - __asm { - mov edx, dest - mov ecx, exchange_value - mov eax, compare_value - lock cmpxchg dword ptr [edx], ecx - } -} +#ifndef AMD64 -template<> -template -inline T Atomic::PlatformCmpxchg<8>::operator()(T volatile* dest, - T compare_value, - T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(8 == sizeof(T)); - int32_t ex_lo = (int32_t)exchange_value; - int32_t ex_hi = *( ((int32_t*)&exchange_value) + 1 ); - int32_t cmp_lo = (int32_t)compare_value; - int32_t cmp_hi = *( ((int32_t*)&compare_value) + 1 ); - __asm { - push ebx - push edi - mov eax, cmp_lo - mov edx, cmp_hi - mov edi, dest - mov ebx, ex_lo - mov ecx, ex_hi - lock cmpxchg8b qword ptr [edi] - pop edi - pop ebx - } -} +#pragma warning(disable: 4035) // Disables warnings reporting missing return statement template<> template inline T Atomic::PlatformLoad<8>::operator()(T const volatile* src) const { STATIC_ASSERT(8 == sizeof(T)); @@ -226,15 +138,12 @@ mov eax, dest fistp qword ptr [eax] } } -#endif // AMD64 - #pragma warning(default: 4035) // Enables warnings reporting missing return statement -#ifndef AMD64 template<> struct Atomic::PlatformOrderedStore<1, RELEASE_X_FENCE> { template void operator()(volatile T* p, T v) const { diff a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp --- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp @@ -209,142 +209,10 @@ #endif // AMD64 return true; } -// Atomics and Stub Functions - -typedef int32_t xchg_func_t (int32_t, volatile int32_t*); -typedef int64_t xchg_long_func_t (int64_t, volatile int64_t*); -typedef int32_t cmpxchg_func_t (int32_t, volatile int32_t*, int32_t); -typedef int8_t cmpxchg_byte_func_t (int8_t, volatile int8_t*, int8_t); -typedef int64_t cmpxchg_long_func_t (int64_t, volatile int64_t*, int64_t); -typedef int32_t add_func_t (int32_t, volatile int32_t*); -typedef int64_t add_long_func_t (int64_t, volatile int64_t*); - -#ifdef AMD64 - -int32_t os::atomic_xchg_bootstrap(int32_t exchange_value, volatile int32_t* dest) { - // try to use the stub: - xchg_func_t* func = CAST_TO_FN_PTR(xchg_func_t*, StubRoutines::atomic_xchg_entry()); - - if (func != NULL) { - os::atomic_xchg_func = func; - return (*func)(exchange_value, dest); - } - assert(Threads::number_of_threads() == 0, "for bootstrap only"); - - int32_t old_value = *dest; - *dest = exchange_value; - return old_value; -} - -int64_t os::atomic_xchg_long_bootstrap(int64_t exchange_value, volatile int64_t* dest) { - // try to use the stub: - xchg_long_func_t* func = CAST_TO_FN_PTR(xchg_long_func_t*, StubRoutines::atomic_xchg_long_entry()); - - if (func != NULL) { - os::atomic_xchg_long_func = func; - return (*func)(exchange_value, dest); - } - assert(Threads::number_of_threads() == 0, "for bootstrap only"); - - int64_t old_value = *dest; - *dest = exchange_value; - return old_value; -} - - -int32_t os::atomic_cmpxchg_bootstrap(int32_t exchange_value, volatile int32_t* dest, int32_t compare_value) { - // try to use the stub: - cmpxchg_func_t* func = CAST_TO_FN_PTR(cmpxchg_func_t*, StubRoutines::atomic_cmpxchg_entry()); - - if (func != NULL) { - os::atomic_cmpxchg_func = func; - return (*func)(exchange_value, dest, compare_value); - } - assert(Threads::number_of_threads() == 0, "for bootstrap only"); - - int32_t old_value = *dest; - if (old_value == compare_value) - *dest = exchange_value; - return old_value; -} - -int8_t os::atomic_cmpxchg_byte_bootstrap(int8_t exchange_value, volatile int8_t* dest, int8_t compare_value) { - // try to use the stub: - cmpxchg_byte_func_t* func = CAST_TO_FN_PTR(cmpxchg_byte_func_t*, StubRoutines::atomic_cmpxchg_byte_entry()); - - if (func != NULL) { - os::atomic_cmpxchg_byte_func = func; - return (*func)(exchange_value, dest, compare_value); - } - assert(Threads::number_of_threads() == 0, "for bootstrap only"); - - int8_t old_value = *dest; - if (old_value == compare_value) - *dest = exchange_value; - return old_value; -} - -#endif // AMD64 - -int64_t os::atomic_cmpxchg_long_bootstrap(int64_t exchange_value, volatile int64_t* dest, int64_t compare_value) { - // try to use the stub: - cmpxchg_long_func_t* func = CAST_TO_FN_PTR(cmpxchg_long_func_t*, StubRoutines::atomic_cmpxchg_long_entry()); - - if (func != NULL) { - os::atomic_cmpxchg_long_func = func; - return (*func)(exchange_value, dest, compare_value); - } - assert(Threads::number_of_threads() == 0, "for bootstrap only"); - - int64_t old_value = *dest; - if (old_value == compare_value) - *dest = exchange_value; - return old_value; -} - -#ifdef AMD64 - -int32_t os::atomic_add_bootstrap(int32_t add_value, volatile int32_t* dest) { - // try to use the stub: - add_func_t* func = CAST_TO_FN_PTR(add_func_t*, StubRoutines::atomic_add_entry()); - - if (func != NULL) { - os::atomic_add_func = func; - return (*func)(add_value, dest); - } - assert(Threads::number_of_threads() == 0, "for bootstrap only"); - - return (*dest) += add_value; -} - -int64_t os::atomic_add_long_bootstrap(int64_t add_value, volatile int64_t* dest) { - // try to use the stub: - add_long_func_t* func = CAST_TO_FN_PTR(add_long_func_t*, StubRoutines::atomic_add_long_entry()); - - if (func != NULL) { - os::atomic_add_long_func = func; - return (*func)(add_value, dest); - } - assert(Threads::number_of_threads() == 0, "for bootstrap only"); - - return (*dest) += add_value; -} - -xchg_func_t* os::atomic_xchg_func = os::atomic_xchg_bootstrap; -xchg_long_func_t* os::atomic_xchg_long_func = os::atomic_xchg_long_bootstrap; -cmpxchg_func_t* os::atomic_cmpxchg_func = os::atomic_cmpxchg_bootstrap; -cmpxchg_byte_func_t* os::atomic_cmpxchg_byte_func = os::atomic_cmpxchg_byte_bootstrap; -add_func_t* os::atomic_add_func = os::atomic_add_bootstrap; -add_long_func_t* os::atomic_add_long_func = os::atomic_add_long_bootstrap; - -#endif // AMD64 - -cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap; - #ifdef AMD64 /* * Windows/x64 does not use stack frames the way expected by Java: * [1] in most cases, there is no frame pointer. All locals are addressed via RSP * [2] in rare cases, when alloca() is used, a frame pointer is used, but this may diff a/src/hotspot/os_cpu/windows_x86/os_windows_x86.hpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.hpp --- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.hpp +++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.hpp @@ -26,38 +26,10 @@ #define OS_CPU_WINDOWS_X86_OS_WINDOWS_X86_HPP // // NOTE: we are back in class os here, not win32 // -#ifdef AMD64 - static int32_t (*atomic_xchg_func) (int32_t, volatile int32_t*); - static int64_t (*atomic_xchg_long_func) (int64_t, volatile int64_t*); - - static int32_t (*atomic_cmpxchg_func) (int32_t, volatile int32_t*, int32_t); - static int8_t (*atomic_cmpxchg_byte_func) (int8_t, volatile int8_t*, int8_t); - static int64_t (*atomic_cmpxchg_long_func) (int64_t, volatile int64_t*, int64_t); - - static int32_t (*atomic_add_func) (int32_t, volatile int32_t*); - static int64_t (*atomic_add_long_func) (int64_t, volatile int64_t*); - - static int32_t atomic_xchg_bootstrap (int32_t, volatile int32_t*); - static int64_t atomic_xchg_long_bootstrap (int64_t, volatile int64_t*); - - static int32_t atomic_cmpxchg_bootstrap (int32_t, volatile int32_t*, int32_t); - static int8_t atomic_cmpxchg_byte_bootstrap(int8_t, volatile int8_t*, int8_t); -#else - - static int64_t (*atomic_cmpxchg_long_func) (int64_t, volatile int64_t*, int64_t); - -#endif // AMD64 - - static int64_t atomic_cmpxchg_long_bootstrap(int64_t, volatile int64_t*, int64_t); - -#ifdef AMD64 - static int32_t atomic_add_bootstrap (int32_t, volatile int32_t*); - static int64_t atomic_add_long_bootstrap (int64_t, volatile int64_t*); -#endif // AMD64 static void setup_fpu(); static bool supports_sse() { return true; } static jlong rdtsc();